package com.eden.manage.service;


import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.eden.manage.dto.PageComDto;
import com.eden.manage.dto.UserFrontDto;
import com.eden.manage.dto.UserInfoDto;
import com.eden.manage.dto.user.UserDto;
import com.eden.manage.mapper.EdenPlatAgentInfoMapper;
import com.eden.manage.mapper.EdenPlatMapper;
import com.eden.manage.mapper.UserInfoMapper;
import com.eden.manage.model.EdenPlat;
import com.eden.manage.model.EdenPlatAgentInfo;
import com.eden.manage.model.UserInfo;
import com.eden.manage.req.query.UserQuery;
import com.eden.manage.utils.ConstantUtils;
import com.eden.manage.utils.WebUserUtils;
import com.eden.manage.utils.mapstruct.UserStructUtils;
import eden.api.common.enums.UserTypeEnum;
import eden.api.common.model.PageQuery;
import eden.api.common.utils.ErrorEnums;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户接口
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserInfoMapper userInfoMapper;

    private final EdenPlatMapper edenPlatMapper;

    private final EdenPlatAgentInfoMapper platAgentInfoMapper;


    public PageComDto<UserDto> pageList(UserQuery userQuery){
        dealDataAuth(userQuery);
        PageComDto<UserDto> userPageDto = new PageComDto();
        int count = userInfoMapper.countByPage(userQuery);
        if(count > 0){
            List<UserDto> userDtos = userInfoMapper.selectPageList(userQuery);
            dealAgentAndPlatName(userDtos);
            dealBelongUnit(userDtos);
            userPageDto.setList(userDtos);
        }
        userPageDto.setCount(count);
        return userPageDto;
    }

    private void dealAgentAndPlatName(List<UserDto> userDtos) {
        if(CollectionUtils.isEmpty(userDtos)){
            return;
        }
        List<Long> platIds = userDtos.stream().filter(m -> !UserTypeEnum.ADMIN.getCode().equals(m.getType())).map(UserDto::getPlatId).distinct().collect(Collectors.toList());
        Map<Long,String> platNameMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(platIds)){
            platNameMap=  Optional.ofNullable(edenPlatMapper.selectListByIds(platIds)).orElse(Collections.emptyList()).stream().collect(Collectors.toMap(EdenPlat::getId, EdenPlat::getPlatName));
        }
        List<Long> agentIds = userDtos.stream().filter(m -> UserTypeEnum.AGENT.getCode().equals(m.getType())).map(UserDto::getAgentId).collect(Collectors.toList());
        Map<Long,String> agentNameMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(agentIds)){
            agentNameMap = Optional.ofNullable(platAgentInfoMapper.selectListByIds(agentIds)).orElse(Collections.emptyList()).stream().collect(Collectors.toMap(EdenPlatAgentInfo::getId, EdenPlatAgentInfo::getAgentName));
        }
        for (UserDto userDto : userDtos) {
            if(!UserTypeEnum.ADMIN.getCode().equals(userDto.getType())){
                userDto.setPlatName(platNameMap.get(userDto.getPlatId()));
                userDto.setAgentName(agentNameMap.get(userDto.getAgentId()));
            }
        }
    }

    /**
     * 生成权限sql语句
     * @param pageQuery 查询条件
     */
    private void dealDataAuth(PageQuery pageQuery) {
        UserInfoDto userInfo = WebUserUtils.getUserInfo();
        if(UserTypeEnum.ADMIN.getCode().equals(userInfo.getType())){
            // 管理员不需要进行条件判断
            return;
        }
        if(UserTypeEnum.PLAT.getCode().equals(userInfo.getType())){
            String sb = "plat_id=" +
                    userInfo.getPlatId() +
                    " and parent_id = 0 ";
            pageQuery.setDataAuth(sb);
        }else{
            String sb = "plat_id=" +
                    userInfo.getPlatId() +
                    " and " +
                    " parent_id = " +
                    userInfo.getAgentId();
            pageQuery.setDataAuth(sb);
        }
    }

    private void dealBelongUnit(List<UserDto> userDtos) {
        if(CollectionUtils.isEmpty(userDtos)){
            return;
        }
        for (UserDto userDto : userDtos) {
            userDto.setBelongUnit(userDto.getBelongUnitInfo());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void editUser(UserDto userDto){
        if(userDto.getId() == null || userDto.getId() <=0){
            // 新增
            UserInfo userInfo = UserStructUtils.INSTANCE.convertDtoToDb(userDto);
            String pwd = DigestUtil.md5Hex(userDto.getUserPassword());
            userInfo.setUserPassword(pwd);
            userInfo.setId(IdWorker.getId());
            userInfo.setCreateTime(LocalDateTime.now());
            userInfo.setUpdateTime(LocalDateTime.now());
            if(userDto.getBelongUnit().startsWith(UserTypeEnum.ADMIN.name())){
                userInfo.setType(UserTypeEnum.ADMIN.getCode());
                userInfo.setParentId(-1L);
            }else if(userDto.getBelongUnit().startsWith(UserTypeEnum.PLAT.name())){
                userInfo.setType(UserTypeEnum.PLAT.getCode());
                userInfo.setPlatId(Long.valueOf(userDto.getBelongUnit().replaceAll(UserTypeEnum.PLAT.name(),"")));
                userInfo.setParentId(-1L);
            }else if(userDto.getBelongUnit().startsWith(UserTypeEnum.AGENT.name())){
                userInfo.setType(UserTypeEnum.AGENT.getCode());
                userInfo.setAgentId(Long.valueOf(userDto.getBelongUnit().replaceAll(UserTypeEnum.AGENT.name(),"")));
                UserInfoDto loginUser = WebUserUtils.getUserInfo();
                userInfo.setPlatId(loginUser.getPlatId());
                if(loginUser.getType().equals(UserTypeEnum.PLAT.getCode())){
                    userInfo.setParentId(0L);
                }else{
                    userInfo.setParentId(loginUser.getAgentDto().getId());
                }
            }
            userInfoMapper.insert(userInfo);
        }else{
            //更新
            userInfoMapper.updateUser(userDto);
        }
    }

    public void deleteUser(String userAccount){
        if(ConstantUtils.ADMIN_ACCOUNT.equals(userAccount)){
            throw new RuntimeException(ErrorEnums.ADMIN_NOT_DEL.name());
        }
        userInfoMapper.deleteByAccount(userAccount);
    }
    public UserFrontDto getUserFrontInfo(){
        UserInfoDto userInfo = WebUserUtils.getUserInfo();
        UserFrontDto userFrontDto = UserFrontDto.builder().userName(userInfo.getUserName())
                .time(String.valueOf(System.currentTimeMillis())).build();
        List<String> authBtnList = new ArrayList<>();
        if(UserTypeEnum.ADMIN.getCode().equals(userInfo.getType())){
            userFrontDto.setRoles(Collections.singletonList("admin"));
            authBtnList.add("memberAdd");
        }else if (UserTypeEnum.PLAT.getCode().equals(userInfo.getType())){
            userFrontDto.setRoles(Collections.singletonList("plat"));
        }else if (UserTypeEnum.AGENT.getCode().equals(userInfo.getType())){
            userFrontDto.setRoles(Collections.singletonList("agent"));
        }
        userFrontDto.setAuthBtnList(authBtnList);
        return userFrontDto;
    }

}
